import { useEffect, useRef, useState, useCallback, useMemo } from "react";
import { gameList } from "../../config/game";
import { useIsMobile } from "@/hooks/use-mobile";

export interface ImageData {
  img: HTMLImageElement | null; // 图片可能为null（未加载完成）
  x: number;
  y: number;
  index: number;
  gameData: {
    name: string;
    desc: string;
    img: string;
  };
  scale: number; // 添加缩放属性
  animationDelay: number; // 添加动画延迟属性
  opacity: number; // 添加透明度属性
  isLoaded: boolean; // 图片是否已加载完成
}

export interface CanvasConfig {
  imgTotal: number;
  rowMax: number;
  lineMax: number;
  imgMargin: number;
}

export const useCanvasSize = () => {
  const [canvasSize, setCanvasSize] = useState({
    width: 0,
    height: 0,
  });

  useEffect(() => {
    const handleResize = () => {
      setCanvasSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    handleResize();

    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return canvasSize;
};

export const useImageData = (
  config: CanvasConfig,
  canvasSize: { width: number; height: number }
) => {
  const [imageData, setImageData] = useState<ImageData[]>([]);
  const isMobile = useIsMobile();

  // 使用固定的图片尺寸 - 基于当前窗口大小，确保整数避免精度问题
  const imgDimensions = useMemo(() => {
    if (typeof window === "undefined")
      return {
        width: 0,
        height: 0,
      };
    // const windowWidth = isMobile
    //   ? Math.round(window.screen.width / 2.7)
    //   : Math.round(window.screen.width / 6.5);

    const windowHeight = isMobile
      ? Math.round(window.screen.height / 3)
      : Math.round(window.screen.height / 2.5);

    const windowWidth = windowHeight / 1.5;

    return {
      width: windowWidth,
      height: windowHeight,
    };
  }, [canvasSize]);

  useEffect(() => {
    // 首先创建占位符数据
    const createPlaceholders = () => {
      const placeholders: ImageData[] = Array.from(
        { length: config.imgTotal },
        (_, i) => {
          const gameData = gameList[i];
          const colIndex = i % config.rowMax;
          const lineIndex = Math.floor(i / config.rowMax);

          // 竖向交错排列：奇数列向下偏移50%图片高度
          const offsetY =
            colIndex % 2 === 1
              ? (imgDimensions.height + config.imgMargin) * 0.5
              : 0;

          // 添加初始向上偏移，让首屏内容更靠上
          const initialOffsetY = -imgDimensions.height; // 向上偏移200px

          const x = colIndex * (imgDimensions.width + config.imgMargin);
          const y =
            lineIndex * (imgDimensions.height + config.imgMargin) +
            offsetY +
            initialOffsetY;

          return {
            img: null, // 占位符阶段图片为null
            x,
            y,
            index: i,
            gameData: {
              name: gameData.name,
              desc: gameData.desc,
              img: gameData.img,
            },
            scale: 0, // 初始缩放为0
            animationDelay: i * 100, // 每个图片延迟100ms
            opacity: 1, // 初始透明度为1（完全可见）
            isLoaded: false, // 标记为未加载
          };
        }
      );

      setImageData(placeholders);
      return placeholders;
    };

    // 异步加载图片
    const loadImages = async (placeholders: ImageData[]) => {
      // 为每个占位符异步加载对应的图片
      placeholders.forEach((placeholder, i) => {
        const img = new Image();
        const gameData = gameList[i];
        img.src = gameData.img;

        img.onload = () => {
          // 图片加载完成后，更新对应的imageData
          setImageData((prevData) =>
            prevData.map((imgData) =>
              imgData.index === i
                ? { ...imgData, img, isLoaded: true }
                : imgData
            )
          );
        };

        img.onerror = () => {
          console.warn(
            `Failed to load image: ${gameData.name} - ${gameData.img}`
          );
          // 即使加载失败，也标记为已处理，保持占位符
          setImageData((prevData) =>
            prevData.map((imgData) =>
              imgData.index === i
                ? { ...imgData, isLoaded: true } // 保持img为null，但标记为已处理
                : imgData
            )
          );
        };
      });
    };

    // 先创建占位符，然后开始加载图片
    const placeholders = createPlaceholders();
    loadImages(placeholders);
  }, [config, imgDimensions]);

  return { imageData, setImageData, imgDimensions };
};

// 惯性滚动 hook
export const useInertiaScroll = (
  moveImages: (deltaX: number, deltaY: number) => void
) => {
  const velocityRef = useRef({ x: 0, y: 0 });
  const lastTimeRef = useRef(0);
  const lastPosRef = useRef({ x: 0, y: 0 });
  const inertiaAnimationRef = useRef<number | null>(null);
  const isInertiaActiveRef = useRef(false);

  // 更新速度
  const updateVelocity = useCallback((x: number, y: number) => {
    const now = Date.now();
    const deltaTime = now - lastTimeRef.current;

    if (deltaTime > 0 && lastTimeRef.current > 0) {
      const deltaX = x - lastPosRef.current.x;
      const deltaY = y - lastPosRef.current.y;

      // 计算速度 (像素/毫秒)
      const vx = deltaX / deltaTime;
      const vy = deltaY / deltaTime;

      // 使用加权平均来平滑速度变化，提高响应度让惯性更强
      const smoothFactor = 0.6;
      velocityRef.current.x =
        velocityRef.current.x * (1 - smoothFactor) + vx * smoothFactor;
      velocityRef.current.y =
        velocityRef.current.y * (1 - smoothFactor) + vy * smoothFactor;
    }

    lastTimeRef.current = now;
    lastPosRef.current = { x, y };
  }, []);

  // 开始惯性滚动
  const startInertia = useCallback(() => {
    if (isInertiaActiveRef.current) return;

    const initialVelocity = { ...velocityRef.current };

    // 速度阈值，低于此值不启动惯性 (降低阈值，更容易触发惯性)
    const minVelocity = 0.02;
    if (
      Math.abs(initialVelocity.x) < minVelocity &&
      Math.abs(initialVelocity.y) < minVelocity
    ) {
      return;
    }

    isInertiaActiveRef.current = true;
    // 放大初始速度，让惯性更强
    let currentVelocity = {
      x: initialVelocity.x * 1.5,
      y: initialVelocity.y * 1.5,
    };

    // 阻尼系数，控制减速快慢 (提高到0.96，减速更慢，惯性更持久)
    const damping = 0.96;
    const minVelocityThreshold = 0.002;

    let lastFrameTime = Date.now();

    const animate = () => {
      const now = Date.now();
      const deltaTime = now - lastFrameTime;
      lastFrameTime = now;

      // 应用阻尼
      currentVelocity.x *= damping;
      currentVelocity.y *= damping;

      // 计算移动距离 (速度 * 实际时间间隔)
      const deltaX = currentVelocity.x * deltaTime;
      const deltaY = currentVelocity.y * deltaTime;

      moveImages(deltaX, deltaY);

      // 检查是否需要继续动画
      if (
        Math.abs(currentVelocity.x) > minVelocityThreshold ||
        Math.abs(currentVelocity.y) > minVelocityThreshold
      ) {
        inertiaAnimationRef.current = requestAnimationFrame(animate);
      } else {
        isInertiaActiveRef.current = false;
      }
    };

    animate();
  }, [moveImages]);

  // 停止惯性滚动
  const stopInertia = useCallback(() => {
    if (inertiaAnimationRef.current) {
      cancelAnimationFrame(inertiaAnimationRef.current);
      inertiaAnimationRef.current = null;
    }
    isInertiaActiveRef.current = false;
    velocityRef.current = { x: 0, y: 0 };
  }, []);

  // 重置速度追踪
  const resetVelocity = useCallback(() => {
    velocityRef.current = { x: 0, y: 0 };
    lastTimeRef.current = 0;
  }, []);

  return {
    updateVelocity,
    startInertia,
    stopInertia,
    resetVelocity,
    isInertiaActive: () => isInertiaActiveRef.current,
  };
};

export const useMouseInteraction = () => {
  const [isDragging, setIsDragging] = useState(false);
  const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 });
  const [startMousePos, setStartMousePos] = useState({ x: 0, y: 0 }); // 记录开始位置
  const [hasMoved, setHasMoved] = useState(false); // 是否发生了移动

  const handleMoveStart = useCallback((x: number, y: number) => {
    setIsDragging(true);
    setLastMousePos({ x, y });
    // 记录开始位置
    setStartMousePos({ x, y });
    // 重置移动状态
    setHasMoved(false);
  }, []);

  const handleMouseUp = useCallback(() => {
    // 不重置hasMoved，让onClick能够判断是否发生了拖拽
    setIsDragging(false);
  }, []);

  const handleMouseLeave = useCallback(() => {
    setIsDragging(false);
  }, []);

  const handleWheel = useCallback(
    (
      e: React.WheelEvent,
      moveImages: (deltaX: number, deltaY: number) => void
    ) => {
      // 滚轮的deltaY值：向上滚动为负值，向下滚动为正值
      // 我们将其反转，让向上滚动时图片向上移动（deltaY为正值）
      const deltaY = -e.deltaY;
      const deltaX = -e.deltaX; // 支持水平滚动（如果有的话）

      // 调用移动图片函数
      moveImages(deltaX, deltaY);
    },
    []
  );

  // 更新touch移动状态
  const handleMove = useCallback(
    (x: number, y: number) => {
      if (isDragging) {
        const deltaX = x - startMousePos.x;
        const deltaY = y - startMousePos.y;
        const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

        // 如果移动距离超过5px，认为是拖拽操作
        if (distance > 5) {
          setHasMoved(true);
        }
      }
    },
    [isDragging, startMousePos]
  );

  // 检查是否真正拖拽了（用于onClick判断）
  const isRealDrag = useCallback(() => {
    return hasMoved;
  }, [hasMoved]);

  // 重置拖拽状态（在onClick后调用）
  const resetDragState = useCallback(() => {
    setHasMoved(false);
  }, []);

  return {
    isDragging,
    lastMousePos,
    setLastMousePos,
    handleMoveStart,
    handleMouseUp,
    handleMouseLeave,
    handleWheel,
    handleMove,
    isRealDrag,
    resetDragState,
  };
};

export const useCanvasRenderer = (
  canvasRef: React.RefObject<HTMLCanvasElement | null>,
  imageData: ImageData[],
  imgDimensions: { width: number; height: number },
  canvasSize: { width: number; height: number }
) => {
  const contextRef = useRef<CanvasRenderingContext2D | null>(null);
  const animationFrameRef = useRef<number | null>(null);
  const [needsRedraw, setNeedsRedraw] = useState(false);
  const startTimeRef = useRef<number>(Date.now());

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || contextRef.current) return;

    const context = canvas.getContext("2d");
    if (context) {
      // 优化渲染性能
      context.imageSmoothingEnabled = true;
      context.imageSmoothingQuality = "high";
    }
    contextRef.current = context;
  }, [canvasRef]);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    canvas.width = canvasSize.width;
    canvas.height = canvasSize.height;

    // 尺寸改变后需要重绘
    setNeedsRedraw(true);
  }, [canvasSize]);

  // 绘制圆角矩形路径
  const drawRoundedRect = useCallback(
    (
      context: CanvasRenderingContext2D,
      x: number,
      y: number,
      width: number,
      height: number,
      radius: number
    ) => {
      context.beginPath();
      context.moveTo(x + radius, y);
      context.lineTo(x + width - radius, y);
      context.quadraticCurveTo(x + width, y, x + width, y + radius);
      context.lineTo(x + width, y + height - radius);
      context.quadraticCurveTo(
        x + width,
        y + height,
        x + width - radius,
        y + height
      );
      context.lineTo(x + radius, y + height);
      context.quadraticCurveTo(x, y + height, x, y + height - radius);
      context.lineTo(x, y + radius);
      context.quadraticCurveTo(x, y, x + radius, y);
      context.closePath();
    },
    []
  );

  // 绘制图片
  const drawImages = useCallback(() => {
    const context = contextRef.current;
    const canvas = canvasRef.current;

    if (!context || !canvas || imageData.length === 0) return;

    context.clearRect(0, 0, canvas.width, canvas.height);

    const currentTime = Date.now();
    let hasAnimation = false;

    // 只绘制在视口内的图片以提高性能
    imageData.forEach((imgData) => {
      // 简单的视口裁剪检查
      if (
        imgData.x + imgDimensions.width >= 0 &&
        imgData.x <= canvas.width &&
        imgData.y + imgDimensions.height >= 0 &&
        imgData.y <= canvas.height
      ) {
        // 计算当前缩放值
        const elapsed =
          currentTime - startTimeRef.current - imgData.animationDelay;
        let currentScale = imgData.scale;

        if (elapsed > 0 && currentScale < 1) {
          const progress = Math.min(elapsed / 600, 1); // 600ms动画时长
          // 使用easeOutBack缓动函数，产生弹性效果
          const easeProgress =
            1 -
            Math.pow(1 - progress, 3) *
              (1 - 0.3 * Math.sin(progress * Math.PI));
          currentScale = easeProgress;
          imgData.scale = currentScale; // 更新缩放值
          hasAnimation = true;
        } else if (currentScale < 1) {
          hasAnimation = true; // 还在等待动画开始
        }

        if (currentScale > 0 && imgData.opacity > 0) {
          // 保存当前状态
          context.save();

          // 设置透明度
          context.globalAlpha = imgData.opacity;

          // 计算缩放后的尺寸和位置
          const scaledWidth = imgDimensions.width * currentScale;
          const scaledHeight = imgDimensions.height * currentScale;
          const offsetX = (imgDimensions.width - scaledWidth) / 2;
          const offsetY = (imgDimensions.height - scaledHeight) / 2;

          // 创建圆角裁剪路径（基于缩放后的尺寸）
          drawRoundedRect(
            context,
            imgData.x + offsetX,
            imgData.y + offsetY,
            scaledWidth,
            scaledHeight,
            10 * currentScale // 圆角也要缩放
          );

          if (imgData.img && imgData.isLoaded) {
            // 如果图片已加载，应用裁剪并绘制图片
            context.clip();
            context.drawImage(
              imgData.img,
              imgData.x + offsetX,
              imgData.y + offsetY,
              scaledWidth,
              scaledHeight
            );
          } else {
            // 设置边框颜色
            context.strokeStyle = "#5e5e5e";
            // 设置边框宽度
            context.lineWidth = 1;
            context.stroke();
            // 如果图片未加载，绘制黑色占位符
            // context.fillStyle = "#bcdcfe"; // 深灰色占位符
            // context.fill();
          }

          // 恢复状态
          context.restore();
        }
      }
    });
  }, [imageData, imgDimensions, canvasRef, drawRoundedRect]);

  // 渲染循环
  useEffect(() => {
    const animate = () => {
      if (needsRedraw) {
        drawImages();
      }
      animationFrameRef.current = requestAnimationFrame(animate);
    };

    if (imageData.length > 0) {
      animate();
    }

    return () => {
      if (animationFrameRef.current !== null) {
        cancelAnimationFrame(animationFrameRef.current);
      }
    };
  }, [drawImages, imageData, needsRedraw]);

  const requestRedraw = useCallback(() => {
    setNeedsRedraw(true);
  }, []);

  return { requestRedraw };
};
